package com.share.all.config;

import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializationContext;

import java.time.Duration;
import java.util.concurrent.TimeUnit;

/**
 * 缓存相关配置
 * @author caifan
 * @since 2023/2/3
 */
@EnableCaching
@Configuration
public class CacheConfig {

    @Value("${caffeine.expire.time:15}")
    private Long caffeineExpireTime;

    @Value("${redis.expire.time:60}")
    private Long redisExpireTime;

    @Value("${caffeine.maxSize:1000}")
    private Integer caffeineMaxSize;

    @Bean("caffeineCacheManager")
    public CacheManager caffeineCacheManager() {
        CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager();
        // caffeine配置
        Caffeine<Object, Object> caffeine = Caffeine.newBuilder()
                // 初始化大小
                .initialCapacity(128)
                //最后一次写入后经过固定时间过期
                .expireAfterWrite(caffeineExpireTime, TimeUnit.SECONDS)
                //缓存的最大条数
                .maximumSize(caffeineMaxSize);
        caffeineCacheManager.setCaffeine(caffeine);
        return caffeineCacheManager;
    }

    @Bean("cacheManager")
    @Primary
    public CacheManager cacheManager(RedisTemplate redisTemplate) {
        // 基本配置
        final RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                // 设置key为String类型
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getStringSerializer()))
                // 设置value为json类型
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()))
                // 不缓存空
                .disableCachingNullValues()
                // 缓存数据保存时间
                .entryTtl(Duration.ofSeconds(redisExpireTime));

        RedisCacheManager redisCacheManager = RedisCacheManager.RedisCacheManagerBuilder
                .fromConnectionFactory(redisTemplate.getConnectionFactory())
                // 缓存配置
                .cacheDefaults(redisCacheConfiguration)
                // 配置同步修改或删除 put/evict
                .transactionAware()
                .build();

        return redisCacheManager;
    }

    @Bean
    public CustomKeyGenerator customKeyGenerator() {
        return new CustomKeyGenerator();
    }
}
